package com.jack.thinking.thread.core._4;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class UseConditionWaitNotify {
	public static void main(String[] args) {
		Lock lock = new ReentrantLock();
		Condition conditionProvider = lock.newCondition();
		Condition conditionConsumer = lock.newCondition();
		List<Integer> list = new ArrayList<>();
		SingleConsumer sc = new SingleConsumer(lock, conditionProvider, conditionConsumer, list);
		SingleProvider sp = new SingleProvider(lock, conditionProvider, conditionConsumer, list);
		SingleConsumer sc1 = new SingleConsumer(lock, conditionProvider, conditionConsumer, list);
		SingleProvider sp1 = new SingleProvider(lock, conditionProvider, conditionConsumer, list);
		SingleConsumer sc2 = new SingleConsumer(lock, conditionProvider, conditionConsumer, list);
		SingleProvider sp2 = new SingleProvider(lock, conditionProvider, conditionConsumer, list);
		SingleConsumer sc3 = new SingleConsumer(lock, conditionProvider, conditionConsumer, list);
		SingleProvider sp3 = new SingleProvider(lock, conditionProvider, conditionConsumer, list);
		SingleConsumer sc4 = new SingleConsumer(lock, conditionProvider, conditionConsumer, list);
		SingleProvider sp4 = new SingleProvider(lock, conditionProvider, conditionConsumer, list);
		SingleConsumer sc5 = new SingleConsumer(lock, conditionProvider, conditionConsumer, list);
		SingleProvider sp5 = new SingleProvider(lock, conditionProvider, conditionConsumer, list);
		sc.start();
		sp.start();
		sc1.start();
		sp1.start();
		sc2.start();
		sp2.start();
		sc3.start();
		sp3.start();
		sc4.start();
		sp4.start();
		sc5.start();
		sp5.start();
	}
}

class SingleConsumer extends Thread{
	private Lock lock;
	private Condition conditionProvider;
	private Condition conditionConsumer;
	private List<Integer> list;
	
	

	public SingleConsumer(Lock lock, Condition conditionProvider, Condition conditionConsumer, List<Integer> list) {
		super();
		this.lock = lock;
		this.conditionProvider = conditionProvider;
		this.conditionConsumer = conditionConsumer;
		this.list = list;
	}



	@Override
	public void run() {
		lock.lock();
		while(list.size() == 0 ) {
			try {
				conditionConsumer.await();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		list.remove(0);
		conditionProvider.signalAll();
		System.out.println("cus -" + Arrays.toString(list.toArray()));
		lock.unlock();
	}
}

class SingleProvider extends Thread{
	private Lock lock;
	private Condition conditionProvider;
	private Condition conditionConsumer;
	private List<Integer> list;
	
	

	public SingleProvider(Lock lock, Condition conditionProvider, Condition conditionConsumer, List<Integer> list) {
		super();
		this.lock = lock;
		this.conditionProvider = conditionProvider;
		this.conditionConsumer = conditionConsumer;
		this.list = list;
	}



	@Override
	public void run() {
		lock.lock();
		while(list.size() == 5 ) {
			try {
				conditionProvider.await();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		list.add(0);
		conditionConsumer.signalAll();
		System.out.println("pro -" + Arrays.toString(list.toArray()));
		lock.unlock();
	}
}